package main

import (
	"fmt"
	"reflect"
)

// 定义一个结构体
type Student struct{
	Name string `json:"name" form:"username"`
	Age int  `json:"age"`
	Score int `json:"score"`
}
func (s Student) GetInfo() string{
	var str =fmt.Sprintf("姓名:%v 年龄:%v 成绩:%v",s.Name,s.Age,s.Score)
	return str
}
func (s Student) SetInfo(name string,age int,score int){
	s.Name =name
	s.Age=age
	s.Score =score
}
func (s Student) Printf(){
	fmt.Println("这是一个打印方法")
}
// 打印字段
func PrintStuctField(s interface{}){
	// 判断参数是否为结构体类型
	t :=reflect.TypeOf(s) //获取类型
	v :=reflect.ValueOf(s) //获取值
	if t.Kind() !=reflect.Struct &&t.Elem().Kind()!=reflect.Struct{
		fmt.Println("传入的参数不是一个结构体")
		return
	}
	// // 通过类型变量里面的Field可以获取结构体的字段
	// // 表示获取结构体里面第0个属性
	// // field0 :=t.Field(0)
	// // field0 :=t.Field(0)
	// // fmt.Println(field0)
	// // fmt.Println("字段名称:",field0.Name)
	// // fmt.Println("字段类型:",field0.Type)
	// // fmt.Println("字段Tag:",field0.Tag.Get("json"))
	// // fmt.Println("字段Tag:",field0.Tag.Get("form"))
	// // 
	// // fmt.Println(field0)

	// // 通过类型变量里面的FieldByName可以获取结构体的字段
	// field1,ok :=t.FieldByName("Age")
	// if ok{
	// fmt.Println("字段名称:",field1.Name)
	// fmt.Println("字段类型:",field1.Type)
	// fmt.Println("字段Tag:",field1.Tag.Get("json"))
	// }
	// // 通过类型变量来获取NumField获取到该结构体有几个字段
	// var fieldCount =t.NumField()
	// fmt.Println(fieldCount)
	// // 通过值变量获取结构体属性对应的值
	// fmt.Println(v.FieldByName("Name"))
	// fmt.Println(v.FieldByName("Age"))
	// fmt.Println("----------------------")
	// // 通过类型变量里面的Method获取这个结构体可以获取结构体方法
	// method0 :=t.Method(0)  //和结构体方法的顺序没关系 和结构体方法的ASCII码有关系
	// fmt.Println(method0.Name)
	// fmt.Println(method0.Type,"\n")
	// // 通过 类型变量获取这个结构体有多少方法
	// method1,ok :=t.MethodByName("Print")
	// if ok{
	// 	fmt.Println(method1.Name)
	// 	fmt.Println(method1.Type)
	// }
	// fmt.Println("--------------------")
	// 通过值变量执行方法
	v.Method(1).Call(nil)
	v.MethodByName("Print").Call(nil)
	info :=v.MethodByName("GetInfo").Call(nil)
	fmt.Println(info)

	// 执行方法传入参数
	var params []reflect.Value
	params = append(params, reflect.ValueOf("李四"))
	params = append(params, reflect.ValueOf(23))
	params =append(params, reflect.ValueOf(99))
	v.MethodByName("SetInfo").Call(params)  //执行方法传入参数
	info1 :=v.MethodByName("GetInfo").Call(nil)
	fmt.Println(info1)
	// 5 h获取方法数量
	fmt.Println("方法数量:",t.NumMethod())

}


func main(){
	// 将结构体实例化
	 stu := Student{
		Name:"小明",
		Age:22,
		Score: 60,
	}
	// 值类型
	// PrintStuctField(stu)
	PrintStuctField(&stu)
	fmt.Printf("%#v",stu)
	
}